package com.mark.article.service.impl;

import com.alibaba.fastjson.JSON;
import com.mark.article.service.ApArticleSearchService;
import com.mark.article.utils.Trie;
import com.mark.common.common.contants.ESIndexConstants;
import com.mark.model.article.dtos.UserSearchDto;
import com.mark.model.article.pojos.ApArticle;
import com.mark.model.article.pojos.ApAssociateWords;
import com.mark.model.article.pojos.ApHotWords;
import com.mark.model.behavior.pojos.ApBehaviorEntry;
import com.mark.model.common.dtos.ResponseResult;
import com.mark.model.common.enums.AppHttpCodeEnum;
import com.mark.model.mappers.app.*;
import com.mark.model.user.pojos.ApUser;
import com.mark.model.user.pojos.ApUserSearch;
import com.mark.utils.threadlocal.AppThreadLocalUtils;
import io.searchbox.client.JestClient;
import io.searchbox.core.Search;
import io.searchbox.core.SearchResult;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @Description :  java类作用描述
 * @Author :  Markburt
 * @CreateDate :  2020/2/25$ 下午 12:47$
 * @UpdateUser :  Markburt
 * @UpdateDate :  2020/2/25$ 下午 12:47$
 * @UpdateRemark :  Project Build
 * @Version :  1.0
 */
@Service
@SuppressWarnings("all")
public class ApArticleSearchServiceImpl implements ApArticleSearchService {


    @Autowired
    private ApBehaviorEntryMapper apBehaviorEntryMapper;

    @Autowired
    private ApUserSearchMapper apUserSearchMapper;

    @Autowired
    private ApHotWordsMapper apHotWordsMapper;

    @Autowired
    private ApAssociateWordsMapper apAssociateWordsMapper;

    @Autowired
    private JestClient jestClient;

    @Autowired
    private ApArticleMapper apArticleMapper;

    @Autowired
    private StringRedisTemplate redisTemplate;

    /**
     * 获取条目ID
     *
     * @param dto
     * @return
     */
    public ResponseResult getEntryId(UserSearchDto dto) {
        ApUser user = AppThreadLocalUtils.getUser();
        // 用户和设备不能同时为空
        if (user == null && dto.getEquipmentId() == null) {
            //缺少参数
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_REQUIRE);
        }
        Long userId = null;
        if (user != null) {
            userId = user.getId();
        }
        ApBehaviorEntry apBehaviorEntry = apBehaviorEntryMapper.selectByUserIdOrEquipemntId(userId, dto.getEquipmentId());
        // 行为实体找以及注册了，逻辑上这里是必定有值得，除非参数错误
        if (apBehaviorEntry == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }
        return ResponseResult.okResult(apBehaviorEntry.getId());
    }

    /**
     * 查询搜索历史
     *
     * @param dto
     * @return
     */
    @Override
    public ResponseResult findUserSearch(UserSearchDto dto) {
        if (dto.getPageSize() > 50 || dto.getPageSize() < 0) {
            //返回无效参数
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }
        //先获取行为实体id
        ResponseResult result = getEntryId(dto);
        if (result.getCode() != AppHttpCodeEnum.SUCCESS.getCode()) {
            return result;
        }
        //查询搜索记录
        List<ApUserSearch> list = apUserSearchMapper.selectByEntryId((int) result.getData(), dto.getPageSize());
        return ResponseResult.okResult(list);
    }


    /**
     * 删除搜索历史
     *
     * @param dto
     * @return
     */
    @Override
    public ResponseResult delUserSearch(UserSearchDto dto) {
        if (dto.getHisList() == null || dto.getPageSize() <= 0) {
            //返回缺少参数
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_REQUIRE);

        }
        //获取行为实体id
        ResponseResult result = getEntryId(dto);
        if (result.getCode() != AppHttpCodeEnum.SUCCESS.getCode()) {
            return result;
        }
        List<Integer> ids = dto.getHisList().stream().map(ApUserSearch::getId).collect(Collectors.toList());
        //通过id修改状态
        int count = apUserSearchMapper.delUserSearch((int) result.getData(), ids);

        return ResponseResult.okResult(count);

    }


    /**
     * 清空搜索历史记录
     *
     * @param dto
     * @return
     */
    @Override
    public ResponseResult clearUserSearch(UserSearchDto dto) {
        ResponseResult responseResult = getEntryId(dto);
        if (responseResult.getCode() != AppHttpCodeEnum.SUCCESS.getCode()) {
            return responseResult;
        }
        int count = apUserSearchMapper.clearUserSearch((int) responseResult.getData());
        return ResponseResult.okResult(count);
    }


    /**
     * 今日热词
     *
     * @param date
     * @return
     */
    @Override
    public ResponseResult hotkeywords(String date) {
        if (StringUtils.isEmpty(date)) {
            date = DateFormatUtils.format(new Date(), "yyyy-MM-dd");
        }
        List<ApHotWords> apHotWords = apHotWordsMapper.queryByHotDate(date);
        return ResponseResult.okResult(apHotWords);
    }


    /**
     * 模糊查询联想词
     *
     * @param dto
     * @return
     */
    @Override
    public ResponseResult searchAssociate(UserSearchDto dto) {
        if (dto.getPageSize() > 50 || dto.getPageSize() < 1) {
            //返回无效参数
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }

        List<ApAssociateWords> apAssociateWords = apAssociateWordsMapper.selectByAssociateWords("%" + dto.getSearchWords() + "%", dto.getPageSize());
        return ResponseResult.okResult(apAssociateWords);
    }


    /**
     * ES 文章分页查询
     *
     * @param dto
     * @return
     */
    @Override
    public ResponseResult esArticleSearch(UserSearchDto dto) {
        //保存搜索记录,只在第一页查询的时候进行保存
        if (dto.getFromIndex() == 0) {
            ResponseResult ret = getEntryId(dto);
            if (ret.getCode() != AppHttpCodeEnum.SUCCESS.getCode()) {
                return ret;
            }
            saveUserSearch((int) ret.getData(), dto.getSearchWords());
        }
        //构建查询条件  jestClient
        //按照关键字查询，分页查询
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        searchSourceBuilder.query(QueryBuilders.matchQuery("title", dto.getSearchWords()));
        searchSourceBuilder.from(dto.getFromIndex());
        searchSourceBuilder.size(dto.getPageSize());
        Search search = new Search.Builder(searchSourceBuilder.toString())
                .addIndex(ESIndexConstants.ARTICLE_INDEX)
                .addType(ESIndexConstants.DEFAULT_DOC).build();
        try {
            SearchResult searchResult = jestClient.execute(search);
            List<ApArticle> apArticles = searchResult.getSourceAsObjectList(ApArticle.class);
            List<ApArticle> resultList = new ArrayList<>();
            for (ApArticle apArticle : apArticles) {
                apArticle = apArticleMapper.selectById(Long.valueOf(apArticle.getId()));
                if (apArticle == null) {
                    continue;
                }
                resultList.add(apArticle);
            }
            //获取结果
            return ResponseResult.okResult(resultList);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
    }


    /**
     * 保存搜索记录
     *
     * @param entryId
     * @param searchWords
     * @return
     */
    @Override
    public ResponseResult saveUserSearch(Integer entryId, String searchWords) {
        //去检查当前数据是否存在
        int count = apUserSearchMapper.checkExist(entryId, searchWords);
        if (count > 0) {
            return ResponseResult.okResult(1);
        }
        //不存在，保存
        ApUserSearch apUserSearch = new ApUserSearch();
        apUserSearch.setEntryId(entryId);
        apUserSearch.setKeyword(searchWords);
        apUserSearch.setStatus(1);
        apUserSearch.setCreatedTime(new Date());
        int insert = apUserSearchMapper.insert(apUserSearch);
        return ResponseResult.okResult(insert);
    }


    /**
     * 搜索联想词 V2版本
     *
     * @param dto
     * @return
     */
    @Override
    public ResponseResult searchAssocicationV2(UserSearchDto dto) {
        if (dto == null || dto.getPageSize() > 50) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }
        String assoStr = redisTemplate.opsForValue().get("associte_list");
        List<ApAssociateWords> aw = null;
        if (StringUtils.isNotEmpty(assoStr)) {
            aw = JSON.parseArray(assoStr, ApAssociateWords.class);
        } else {
            aw = apAssociateWordsMapper.selectAllAssociateWords();
            redisTemplate.opsForValue().set("associte_list", JSON.toJSONString(aw));

        }

        //使用trie来进行管理数据
        Trie t = new Trie();
        for (ApAssociateWords a : aw) {
            t.insert(a.getAssociateWords());
        }
        List<String> ret = t.startWith(dto.getSearchWords());
        List<ApAssociateWords> list = new ArrayList<>();
        for (String s : ret) {
            ApAssociateWords apAssociateWords = new ApAssociateWords();
            apAssociateWords.setAssociateWords(s);
            list.add(apAssociateWords);
        }
        return ResponseResult.okResult(list);

    }


}
